package com.yc.cloud.openai.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.plexpt.chatgpt.ChatGPTStream;
import com.plexpt.chatgpt.entity.chat.ChatCompletion;
import com.plexpt.chatgpt.entity.chat.Message;
import com.plexpt.chatgpt.listener.SseStreamListener;
import com.yc.cloud.basic.exception.Asserts;
import com.yc.cloud.openai.constants.HFJKConstants;
import com.yc.cloud.openai.dto.*;
import com.yc.cloud.openai.dto.resp.HFKJNLPResp;
import com.yc.cloud.openai.dto.resp.LinkAINLPStreamResp;
import com.yc.cloud.openai.request.NLPParam;
import com.yc.cloud.openai.request.TTSParam;
import com.yc.cloud.openai.service.NLPService;
import com.yc.cloud.openai.service.tts.TTSService;
import com.yc.cloud.openai.sse.SseEmitterUTF8;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service("linkAINLPServiceImpl")
@Slf4j
public class LinkAINLPServiceImpl implements NLPService {


    // API URL
    private static final String apiUrl = "https://api.link-ai.tech/v1/chat/completions";
    private static final String openaiUrl = "https://apikeyplus.com/v1/chat/completions";
    // 构建请求头
    private static final String authorizationToken = "Bearer Link_t6B2FIbedKMTvsDjFPztyVSc4w2tVMtQLUkIVNRmiW";

    private Pattern pattern;

    private static final String PREFIX_ANSWER = "请通过下面的编号查询:";
    private static final String PREFIX_ANSWER2 = "请通过下面的编号查询：";
    private final WebClient webClient;
    private TTSService ttsService;

//    public LinkAINLPServiceImpl(WebClient.Builder webClientBuilder, TTSService ttsService) {
//        this.webClient = webClientBuilder.build();
//        this.ttsService = ttsService;
//    }

    public LinkAINLPServiceImpl(@Qualifier("XFTTSServiceImpl") TTSService ttsService) {
        String regex = "\\d{17}";
        pattern = Pattern.compile(regex);
        this.webClient = WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
                .build();
        this.ttsService = ttsService;
    }

    public static void main(String[] args) {
        String content = "根据提供的编号13570935443165184";
        String regex = "\\d{17}";
        val pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            content = matcher.group(0);
        }
        log.info("content=" + content);
    }

    @Override
    public NLPResultDTO getNLPResult(NLPParam param) {
        // 构建请求体
        val jsonArray = JSONUtil.createArray();
        jsonArray.add(JSONUtil.createObj().set("role", "user").set("content", param.getContent()).set("stream", param.getStream()));
        String requestBody = JSONUtil.createObj().set("app_code", param.getAppid()).set("messages", jsonArray).toString();
        val authorization = "Bearer " + param.getAppKey();
        log.info("LinkAINLPServiceImpl requestBody--->{},authorization-->{}", requestBody, authorization);
        // 发送 POST 请求
        val nlpStartTime = System.currentTimeMillis();
        try (HttpResponse response = HttpRequest.post(apiUrl).header("Content-Type", "application/json") // 设置内容类型为 JSON
                .header("Authorization", authorization) // 设置认证头
                .body(requestBody) // 设置请求体
                .execute()) {
            val nlpResult = response.body();
            long nlpEndTime = System.currentTimeMillis();
            val nlpCostTime = nlpEndTime - nlpStartTime;
            log.info("LinkAINLPServiceImpl Spend Times--->{}", nlpCostTime);
            log.info("LinkAINLPServiceImpl RESULT--->{}", nlpResult);
            val nlpResp = JSONUtil.toBean(nlpResult, HFKJNLPResp.class);

            val choiceList = nlpResp.getChoices();
            //没有任何选择,直接返回空
            if (CollUtil.isEmpty(choiceList)) {
                return null;
            }
            val result = new NLPResultDTO();
            //获取答案置信度最高的一个
            var content = choiceList.get(0).getMessage().getContent();
            log.info("LinkAINLPServiceImpl RESULT content--->{}", content);
            //有些回答内容较长的结果，会影响ai响应速度,这边通过业务的方式只记录了问题编号,通过问题编号在从自己的答案库里找答案
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                content = matcher.group(0);
            }
            log.info("getNLPResult content--->{}", content);
            // content = content.replace(PREFIX_ANSWER, "").replace(PREFIX_ANSWER2, "").trim();
            result.setResult(content);
            result.setCostTime(nlpCostTime);
            //直接拿第一个选项内容作为结果
            return result;

        } catch (Exception e) {
            e.printStackTrace();
            Asserts.fail(HFJKConstants.NLP_SERVICE_ERROR);
        }
        return null;
    }

    @Override
    public Flux<String> getNLPResultByStream(NLPParam param) {
        val jsonArray = JSONUtil.createArray();
        jsonArray.add(JSONUtil.createObj().set("role", "user").set("content", param.getContent()));
        String requestBody = JSONUtil.createObj().set("stream", param.getStream()).set("app_code", param.getAppid()).set("messages", jsonArray).toString();
        val authorization = "Bearer " + param.getAppKey();
// 创建一个线程安全的累加器
        StringBuilder totalResultBuilder = new StringBuilder();
        return webClient.post()
                .uri(apiUrl)
                .header(HttpHeaders.AUTHORIZATION, authorization)
                .header("Content-Type", "application/json")
                .bodyValue(requestBody)
                .retrieve()
                .onStatus(HttpStatus::isError, clientResponse ->
                        clientResponse.bodyToMono(String.class)
                                .flatMap(responseBody -> {
                                    // 处理错误的响应体
                                    log.error("Error response body: {}", responseBody);
                                    return Mono.error(new RuntimeException("Error occurred during API call: " + responseBody));
                                })
                )
                .bodyToFlux(String.class);
//                .mapNotNull(chunk -> {
//                    //log.info("Received chunk: {}", chunk);
//                    //整个流结束
//                    if ("[DONE]".equals(chunk)) {
//                        val totalResult = totalResultBuilder.toString();
//                        log.info("totalResultBuilder:{}", totalResult);
//                        return new NlpChunkResultDto(true, "");
//                    }
//                    String data = parseChunk(chunk);
//                    log.info("Received data: {}", data);
//                    //把null值转为空字符串
//                    if (StrUtil.isEmpty(data)) {
//                        data = "";
//                    }
//                    totalResultBuilder.append(data);
//                    return new NlpChunkResultDto(false, data);
//                });
    }


    private String parseChunk(String chunk) {
        val nlpChunkDto = JSONUtil.toBean(chunk, NlpChunkDto.class);
        val choiceList = nlpChunkDto.getChoices();
        if (CollUtil.isEmpty(choiceList)) {
            return null;
        }
        if (choiceList.get(0).getDelta() != null) {
            return choiceList.get(0).getDelta().getContent();
        }
        return null;
    }

    // JSON 解析方法
    private String parseBody(String body) {
        if ("[DONE]".equals(body)) {
            return "";
        }
        LinkAINLPStreamResp nlpResp = JSONUtil.toBean(body, LinkAINLPStreamResp.class);
        val choiceList = nlpResp.getChoices();
        if (CollUtil.isEmpty(choiceList)) {
            return "";
        }
        OpenAiResultDto result = new OpenAiResultDto();
        try {

            result.setNlpContent(choiceList.get(0).getDelta().getContent());
        } catch (Exception e) {
            e.printStackTrace();
        }

//        if (StringUtils.isNotEmpty(content)) {
//            Matcher matcher = pattern.matcher(content);
//            if (matcher.find()) {
//                content = matcher.group();
//            }
//        }

        return "";
    }

    @Override
    public Flux<ServerSentEvent<String>> getNLPResultByStream2(NLPParam param) {
        val jsonArray = JSONUtil.createArray();
        jsonArray.add(JSONUtil.createObj().set("role", "user").set("content", param.getContent()));
        String requestBody = JSONUtil.createObj().set("stream", param.getStream()).set("app_code", param.getAppid()).set("messages", jsonArray).toString();
        val authorization = "Bearer " + param.getAppKey();

        // 使用 bodyToFlux(DataBuffer.class) 获取原始数据流
        Flux<String> dataBufferFlux = webClient.post()
                .uri(apiUrl)
                .header(HttpHeaders.AUTHORIZATION, authorization)
                .header("Content-Type", "application/json")
                .bodyValue(requestBody)
                .retrieve()
                .bodyToFlux(DataBuffer.class)
                .map(dataBuffer -> {
                    // 处理每个数据缓冲区
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    DataBufferUtils.release(dataBuffer);
                    return new String(bytes, StandardCharsets.UTF_8);
                });

        // 处理 DataBuffer 流并拆分消息
        return dataBufferFlux
                .doOnNext(data -> log.info("Sending: {}", data))
                .map(data -> ServerSentEvent.builder(data).build());

    }

    @Override
    public SseEmitter getNLPResultByStream3(NLPParam nlpParam) {
        SseEmitterUTF8 sseEmitter = new SseEmitterUTF8(-1L);
        SseStreamListener listener = new SseStreamListener(sseEmitter);
        //ConsoleStreamListener listener = new ConsoleStreamListener();
        Message message = Message.of(nlpParam.getContent());

        ChatCompletion chatCompletion = ChatCompletion.builder()
                .model("gpt-3.5-turbo")
                .messages(Arrays.asList(message))
                .stream(true)
                .temperature(1)
                .topP(1)
                .presencePenalty(0)
                .frequencyPenalty(0)
//                .maxTokens(250)
                .build();

        // 不需要代理的话，注销此行
        //Proxy proxy = Proxys.http("192.168.1.98", 7890);
//        ChatGPTStream chatGPTStream = ChatGPTStream.builder()
//                .timeout(600)
//                //sk-vSb8TxdeDBQXSx3i61BdEaAbDd234b6e99A0E5796f7892Af
//                //https://apikeyplus.com/
//                .apiKey("sk-vSb8TxdeDBQXSx3i61BdEaAbDd234b6e99A0E5796f7892Af")
//                //.proxy(proxy)
//                .apiHost("https://apikeyplus.com/")
//                .build()
//                .init();

        ChatGPTStream chatGPTStream = ChatGPTStream.builder()
                .timeout(600)
                //sk-vSb8TxdeDBQXSx3i61BdEaAbDd234b6e99A0E5796f7892Af
                //https://apikeyplus.com/         https://api.link-ai.tech/     Link_MDL66qSUECziluJX0Qq77A7RUT2oqRjkDbfxaaQJGc-
                .apiKey("sk-vSb8TxdeDBQXSx3i61BdEaAbDd234b6e99A0E5796f7892Af")
                //.proxy(proxy)
                .apiHost("https://apikeyplus.com/")
                .build()
                .init();

        chatGPTStream.streamChatCompletion(chatCompletion, listener);
        listener.setOnComplate(msg -> {
            //回答完成，可以做一些事情
            sseEmitter.complete();
            System.out.println(msg);
        });
        return sseEmitter;
    }

    // 拆分消息的逻辑（根据您的具体情况实现）
    private Flux<String> processAndSplitMessages(String str) {
        // 这里需要您提供逻辑来拆分和处理消息
        // 假设每条消息都是独立的 JSON 对象，并且以换行符分隔
        return Flux.fromArray(str.split("\n"))
                .filter(line -> !line.isEmpty());
    }


}
